package com.one.blocks.rbac.manager;

import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.one.blocks.mvc.manager.AbstractManager;
import com.one.blocks.mvc.util.ScopeWebRequestHelper;
import com.one.blocks.mvc.valid.validator.AllocatedDataManager;
import com.one.blocks.rbac.domain.SysRole;
import com.one.blocks.rbac.domain.SysUserRole;
import com.one.blocks.rbac.enums.RoleTypeEnum;
import com.one.blocks.rbac.mapper.SysRoleMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintValidatorContext;
import java.util.List;

import static com.one.blocks.rbac.constant.RbacConstant.RoleCache;
import static com.one.blocks.rbac.constant.RbacConstant.ScopeRequest.ROLES_OF_USER_ID;

/**
 * @author <a href="mailto:idler41@163.con">idler41</a> created on 2023-10-25 10:50:39
 */
@Service
public class SysRoleManager extends AbstractManager<SysRoleMapper, SysRole> implements AllocatedDataManager<Integer[]> {

    @Autowired
    private SysRoleManager sysRoleManager;

    @Autowired
    private SysUserRoleManager sysUserRoleManager;

    @Autowired
    private SysRoleMenuManager sysRoleMenuManager;

    @Autowired
    public SysRoleManager(SysRoleMapper mapper) {
        super(mapper);
    }

    @Cached(area = RoleCache.AREA, name = RoleCache.NAME, key = RoleCache.USER_ID + "+args[0]", cacheType = CacheType.BOTH)
    public List<SysRole> findByUserId(Integer userId) {
        return mapper.selectByUserId(userId);
    }

    @Override
    public boolean findAllocatedData(Integer[] roleIds, ConstraintValidatorContext context) {
        Integer userId = sysUserRoleManager.findOneByRoleIds(roleIds);
        if (userId != null) {
            return false;
        }
        Integer menuId = sysRoleMenuManager.findOneByRoleIds(roleIds);
        return menuId != null;
    }

    @CacheInvalidate(area = RoleCache.AREA, name = RoleCache.NAME, key = RoleCache.USER_ID + "+args[0]")
    public void grant(Integer userId, List<SysUserRole> sysUserRoles) {
        sysUserRoleManager.deleteByUserId(userId);
        sysUserRoleManager.insertBatch(sysUserRoles);
    }

    public boolean isAdminRole(Integer userId) {
        List<SysRole> sysRoleList = ScopeWebRequestHelper.get(ROLES_OF_USER_ID + userId,
                () -> sysRoleManager.findByUserId(userId));
        return CollectionUtils.isNotEmpty(sysRoleList) && sysRoleList.stream().anyMatch(i -> RoleTypeEnum.ADMIN.match(i.getType()));
    }
}